<?php

/**
 * 描述：一群猴子排成一圈，按1,2,…,n依次编号。然后从第1只开始数，数到第m只,把它踢出圈，从它后面再开始数，再数到第m只，在把它踢出去…，如此不停的进行下去，直到最后只剩下一只猴子为止，那只猴子就叫做大王。要求编程模拟此过程，输入m、n, 输出最后那个大王的编号。
 */
class 约瑟夫环
{
    /**
     * 数组模拟
     */
    public function 数组模拟解法($total, $num)
    {
        // 构造一个数组
        $arr = range(1, $total);
        // 从1开始
        $i = 1;
        while (count($arr) > 1) {
            ($i % $num != 0) && array_push($arr, $arr[$i - 1]);
            unset($arr[$i - 1]);
            $i++;
        }
        return $arr[$i - 1];
    }

    /**
     * 使用递归 f(N,M)=(f(N−1,M)+M)%N
     */
    public function 递归解法($total, $num)
    {
        if ($total == 1) {
            return 0;
        }
        return ($this->递归解法($total - 1, $num) + $num) % $total;
    }

    /**
     * 因递归有回溯的过程，使用直接迭代的方式代替
     */
    public function 迭代递归解法($total, $num)
    {
        $result = 0;
        for ($i = 1; $i <= $total; $i++) { 
            $result = ($result + $num) % $i;
        }

        return $result;
    }
}

$实例 = new 约瑟夫环();

$编号1 = $实例->数组模拟解法(100, 6);
$编号2 = $实例->递归解法(100, 6) + 1;
$编号3 = $实例->迭代递归解法(100, 6) + 1;

echo $编号1 . PHP_EOL;
echo $编号2 . PHP_EOL;
echo $编号3 . PHP_EOL;